-
Notifications
You must be signed in to change notification settings - Fork 252
chore: find reverted gmp transactions in live mode #12311
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
f04b63d to
28b2ce9
Compare
|
Logs from earlier e2e testing specifically if tx is made by the Wallet Owner: Logs when tx is made non-owner of the Wallet: I’ve made many updates since the last round of testing, so I will need to do E2E testing again. |
5bfdeab to
51dd6d0
Compare
74778d6 to
5d58219
Compare
b9fde86 to
b8b1099
Compare
|
E2E testing results Success Case
Revert Case(Authorized User)
|
…12327) closes: - https://github.com/Agoric/agoric-private/issues/699 ## Description Publishes the expected `sourceAddress` (LCA) for pending GMP transactions into vstorage and updates snapshots accordingly. This enables the GMP watcher to reliably classify reverted Wallet executions by comparing the decoded `sourceAddress` from `calldata` against the expected value, avoiding revert simulation and state-drift issues(see #12311). ### Testing Considerations The vstorage snapshot tests are enough to verify this change. ### Upgrade Considerations - Will require a `ymax0` and `ymax1` update on mainnet.
|
Base branch is changed to master. Please re-run the integration tests by adding 'force:integration' label. |
Revert Case(Non-Authorized)
|
b8b1099 to
183e078
Compare
| if (result.settled) { | ||
| const reason = `${logPrefix} Live mode completed`; | ||
| log(reason); | ||
| abortController.abort(reason); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about handling tx not settled here?
| return { settled: false }; | ||
| } | ||
|
|
||
| deleteTxBlockLowerBound(kvStore, txId); | ||
| return { found: true, txHash: matchingEvent.transactionHash }; | ||
| return { settled: true, txHash: matchingEvent.transactionHash }; | ||
| } catch (error) { | ||
| log(`Error:`, error); | ||
| return { found: false }; | ||
| return { settled: false }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need some extra identifier to differentiate b/w not found and error? Because both says settled: false
| `Watching for MulticallStatus and MulticallExecuted events for txId: ${txId} at contract: ${contractAddress}`, | ||
| ); | ||
| // Named so we can remove it | ||
| const onAbort = () => finish({ settled: false }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we wanna explicitly log when we aborted signal? Might help in debugging.
| ws.off('message', messageHandler); | ||
| ws.off('error', onWsError); | ||
| ws.off('close', onWsClose); | ||
| signal?.removeEventListener('abort', onAbort); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a log say: "Cleaning up ws and listeners"..?
| if (!done) { | ||
| log( | ||
| `✗ No MulticallStatus or MulticallExecuted found for txId ${txId} within ${timeoutMs / 60000} minutes`, | ||
| ); | ||
| const { status, errorMessage } = await findTxStatusFromAxelarscan( | ||
| txId, | ||
| contractAddress, | ||
| { | ||
| axelarApiUrl, | ||
| fetch, | ||
| }, | ||
| `✗ No transaction status found for txId ${txId} within ${ | ||
| timeoutMs / 60000 | ||
| } minutes`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see we make done = true on failure as well. So done essentially means that tx is processed? Either success/failed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, done means the watcher is finished (stopped watching), regardless of whether the transaction succeeded, failed, or was never observed.
| if (receipt.status === 1 && matchingLog) { | ||
| log( | ||
| `✅ SUCCESS: txId=${txId} txHash=${txHash} block=${receipt.blockNumber}`, | ||
| ); | ||
| return finish({ settled: true, txHash }); | ||
| } | ||
|
|
||
| if (receipt.status === 0) { | ||
| /** | ||
| * Transaction reverted - since we've already validated that the sourceAddress | ||
| * matches our expected LCA address, this is a legitimate execution attempt | ||
| * from our own wallet that failed. We treat this as a transaction failure. | ||
| * | ||
| * Note: Spurious executions from unauthorized parties are already filtered | ||
| * out by the sourceAddress check above, so any revert we see here represents | ||
| * a genuine failure of the user's operation. | ||
| */ | ||
| log( | ||
| `❌ REVERTED: txId=${txId} txHash=${txHash} block=${receipt.blockNumber} - transaction failed`, | ||
| ); | ||
| return finish({ settled: true, txHash }); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find it troubling that these two cases collapse into indistinguishable output.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for commenting on this. Looks like I messed it up while defining settled field in all watchers.
| subId = await provider.send('eth_subscribe', [ | ||
| 'alchemy_minedTransactions', | ||
| { | ||
| addresses: [{ to: contractAddress }], | ||
| includeRemoved: false, | ||
| hashesOnly: false, | ||
| }, | ||
| ]); | ||
|
|
||
| ws.on('message', messageHandler); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any chance of a race here? Our general pattern is to register listeners before creating circumstances that could cause them to be invoked.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed to attach the message handler before subscribing.
For additional context: at the contract level, we also follow this pattern - we publish the pending tx entry to vstorage before making the GMP call (see pos-gmp.flows.ts#L540-L566), which gives the watcher 50s-3min to start up before the transaction could complete. So we have protection at both levels.
| // Attach listeners (all removable) | ||
| ws.on('error', onWsError); | ||
| ws.on('close', onWsClose); | ||
| signal?.addEventListener('abort', onAbort); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, same issue. Fixed to attach the error/close listeners immediately after defining them
09dd75a to
edd72dd
Compare
|
Things are working as expected: Portfolio64 logs:Logs for
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
other than tests, this file isnt in use. it would make sense to probably remove it entirely and remove tests related to it as well
e4e2e05 to
4047914
Compare
4047914 to
997315d
Compare
closes:
Description
Removes the dependency on AxelarScan for GMP transaction failure status detection. Instead, it now uses Alchemy WebSocket connections to detect failed GMP transactions on EVM. Alchemy WebSockets are used for both failure and success detection.
This functionality is currently implemented in the live mode of the GMP watcher. Support for lookback mode will be added in a subsequent PR, as detecting reverted transactions in historical logs requires a different mechanism.
Testing Considerations
Existing tests have been adapted to the new changes. Mocks were updated as well. And couple of new tests were added for testing revert behavior.
Upgrade Considerations